#ifndef THMAR_MQTT_CLIENT_H
#define THMAR_MQTT_CLIENT_H

#include <stdint.h>
#include <pthread.h>
#include "thmar_config.h"

/* 消息分发器，用于将接收到的消息分发到对应的回调函数 */ 
/* 消息接收回调函数 */
/* context: 回调函数的上下文 */
/* channel: 订阅的频道名称 */
/* channelLength: 频道名称长度，如果为0，则channel为'\0'结尾，回调函数中可以直接使用字符串操作，否则需要使用channelLength来获取字符串长度 */
/* message: 接收到的消息内容 */
/* messageLength: 接收到的消息内容 */
/* length: 消息长度 */
/* 参见 dispatcher() */
typedef void (*ChannelDispatcher)(void* context, const char* channel,size_t channelLength, const char* message, size_t messageLength);
/** 消息处理器 */
/** context: 消息处理器的上下文 */
/** message: 接收到的消息内容 */
/** length: 消息长度 */
/** 参见 registerChannel() */
/* 注意：如果之前已经设置过消息处理器，则会覆盖之前的消息处理器 */
typedef void (*MessageAdapter)(void *context, const char* message, size_t length);

/** 遍历注册的频道名称的回调函数 */
/** context: 回调函数的上下文 */
/** channel: 注册的频道名称 */
/* 参见 foreachChannel() */
typedef void (*NextRegisteredChannel)(void* context, const char* channel);

/* MQTT客户端抽象接口(C++) */
#ifdef __cplusplus
namespace smq {


/** MQTT客户端抽象接口 */
/** 该接口用于连接MQTT服务器，发布消息，接收消息，订阅/取消订阅频道，设置消息分发器等 */
/** 该接口的实现类必须实现以下接口： */
/** connect()：连接MQTT服务器 */
/** disconnect()：断开MQTT连接 */
/** publish()：发布消息 */
/** subscribe()：订阅频道 */
/** unsubscribe()：取消订阅频道 */
class ThmarMqttClient {
public:
    ThmarMqttClient();
    virtual ~ThmarMqttClient();
public:
    // 连接MQTT服务器
    // 返回值：0表示成功，其他表示失败
    virtual int connect() = 0;
    // 断开MQTT连接
    // 注意：调用该函数后，ThmarMqttClient对象将不再可用
    // 建议在程序退出前调用该函数
    virtual void disconnect() = 0;
    virtual int publish(const char* channel, const char* message) = 0;
    virtual int subscribe(const char* channel) = 0;
    /** 取消订阅topic */ 
    virtual int unsubscribe(const char* channel) = 0;
public:
    /* 设置消息分发器 */ 
    /* 注意：如果之前已经设置过消息分发器，则会覆盖之前的消息分发器 */
    /* context: 消息分发器的上下文 */
    /* dispatcher: 消息分发器 */
    /* 返回值：0表示成功，其他表示失败 */
    int dispatcher(void* context, ChannelDispatcher dispatcher);
    /* 注册一个频道，并设置回调函数 */
    /* 1. 查找channel是否已经注册过 */ 
    /* 2. 如果已经注册过, 则更新回调函数 */ 
    /* 3. 如果没有注册过, 则创建ChannelContext, 并添加到哈希表中, 并订阅channel */ 
    /* 4. 返回THMR_OK */ 
    /* channel: 频道名称 */ 
    /* context: 回调函数的上下文 */ 
    /* dispatcher: 消息回调函数 */ 
    /* 返回值：0表示成功，其他表示失败 */ 
    int registerChannel(const char* channel, void* context, MessageAdapter dispatcher);
    /* 注销channel */
    /* 1. 查找channel是否注册过 */ 
    /* 2. 如果注册过, 则从哈希表中删除, 并取消订阅channel */ 
    /* 3. 返回THMR_OK */ 
    /* 返回值：0表示成功，其他表示失败 */ 
    /* channel: 频道名称 */
    int unregisterChannel(const char* channel);
    /* 遍历所有注册的频道名称 */ 
    /* next: 遍历回调函数 */ 
    void foreachChannel(void* context, NextRegisteredChannel next);
    /* 启动MQTT客户端 */ 
    /* 返回值：0表示成功，其他表示失败 */ 
    int start(void);
    /* 停止MQTT客户端 */ 
    /* 注意：调用该函数后，ThmarMqttClient对象将不再可用 */ 
    /* 建议在程序退出前调用该函数 */ 
    void stop(void);
public:
    /* 分发器上下文 */
    void* dispatcherContext;
    /** 消息分发器 */
    ChannelDispatcher channelDispatcher;
    /** 频道订阅注解同步锁 */
    pthread_mutex_t channelLock;
};

} // namespace smq
#endif // __cplusplus

/* ThmarMqttClient C接口定义 */
/* 定义ThmarMqttClient客户端类型的指针类型 */
typedef void* thmar_mqtt_client_t;

/* 设置消息分发器 */
THMAR_API int thmar_mqtt_client_dispatcher(thmar_mqtt_client_t client, void* context, ChannelDispatcher dispatcher);

/* 注册一个频道，并设置回调函数 */
THMAR_API int thmar_mqtt_client_register_channel(thmar_mqtt_client_t client, const char* channel, void* context, MessageAdapter dispatcher);

/* 注销channel */
THMAR_API int thmar_mqtt_client_unregister_channel(thmar_mqtt_client_t client, const char* channel);

/* 遍历所有注册的频道名称 */
THMAR_API void thmar_mqtt_client_foreach_channel(thmar_mqtt_client_t client, void* context, NextRegisteredChannel next);

/* 启动MQTT客户端 */
THMAR_API int thmar_mqtt_client_start(thmar_mqtt_client_t client);

/* 停止MQTT客户端 */
THMAR_API void thmar_mqtt_client_stop(thmar_mqtt_client_t client);


#endif // THMAR_MQTT_CLIENT_H